package botcraft.client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;

import botcraft.game.Game;
import botcraft.game.ObjectManager;

public abstract class Client implements Runnable {
	private static final Logger logger = Logger.getLogger(Client.class.getName());
	
	protected final ObjectManager objectManager;
	private final Socket socket;
	protected final BufferedReader input;
	private final PrintWriter output;
	protected final Game game;
	
	public Client(final String host, final int port) throws ClassNotFoundException, IOException {
		objectManager = new ObjectManager();
		socket = new Socket(host, port);
		input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		output = new PrintWriter(socket.getOutputStream());
		logger.info("Connected to " + this);
		final URL gameUrl = new URL(input.readLine());
		game = new Game(objectManager, gameUrl);
		logger.info("Loaded game " + gameUrl);
	}
	
	@Override
	public void run() {
		final Thread sender = new Thread(new Sender(this, output));
		final Thread receiver = new Thread(new Receiver(this, input));
		receiver.start();
		sender.start();
		try {
			sender.join();
			receiver.join();
		} catch (InterruptedException e) {
			return;
		} finally {
			try {
				socket.shutdownInput();
				socket.shutdownOutput();
				socket.close();
				logger.info("Closed connection to " + this);
			} catch (IOException e) {
				logger.log(Level.WARNING, "Error closing connection to " + this, e);
			}
		}
	}
	
	@Override
	public String toString() {
		return socket.getInetAddress().toString();
	}
	
	protected abstract String issueCommand();
	protected abstract void executeCommand(final String command);
}
